<?php

/**
 * Data validation types - general purpose classes
 *
 * A range of DataValidator classes for use in form validation with
 * FormObserver objects.  This code is based on a concept published on DevShed
 * http://www.devshed.com/c/a/PHP/¬
 * Centralizing-the-Validation-of-Data-with-the-Observer-Pattern-in-PHP/
 * and was adapted for PHP4 by Stuart Metcalfe
 *
 * @author Stuart Metcalfe <shoopdev@googlemail.com>
 * @version 1.0
 */

/**
 * String validator class to validate a form field as a string.
 */
class StringValidator extends DataValidator
{
	/**
	 * Constructor method
	 *
	 * @access public
	 * @param object $formObserver The FormObserver to contain this validator
	 */
	function StringValidator(&$formObserver)
	{
		parent::DataValidator($formObserver);
	}
	
	/**
	 * validate method for string validator class
	 *
	 * Must not be empty and must contain between $min and $max characters to
	 * be valid
	 *
	 * @access public
	 * @param string $field Name of the form field
	 * @param string $errorMsg Message to be displayed if the field isn't valid
	 * @param int $min The minimum size allowed for the string (default=4)
	 * @param int $max The maximum size allowed for the string (default=32)
	 * @return boolean Whether the field validated or not
	 */
	function validate($field,$errorMsg,$min=4,$max=32)
	{
		parent::validate($field);
		
		if(!isset($this->_method[$field]) || trim($this->_method[$field])=='' || strlen($this->_method[$field])<$min || strlen($this->_method[$field])>$max)
		{
			$this->notifyObserver($errorMsg);
			return false;
		}
		
		return true;
	}
}

/**
 * Integer validator class to validate a form field as an integer.
 */
class IntegerValidator extends DataValidator
{
	/**
	 * Constructor method
	 *
	 * @access public
	 * @param object $formObserver The FormObserver to contain this validator
	 */
	function IntegerValidator(&$formObserver)
	{
		parent::DataValidator($formObserver);
	}
	
	/**
	 * validate function for integer validator class
	 *
	 * Must be an integer to be valid
	 *
	 * @access public
	 * @param string $field Name of the form field
	 * @param string $errorMsg Message to be displayed if the field isn't valid
	 * @return boolean Whether the field validated or not
	 */
	function validate($field,$errorMsg)
	{
		parent::validate($field);
		
		if(!isset($this->_method[$field]) || !is_numeric($this->_method[$field]) || intval($this->_method[$field])!=$this->_method[$field])
		{
			$this->notifyObserver($errorMsg);
			return false;
		}
		
		return true;
	}
}

/**
 * Number validator class to validate a form field as a number.
 */
class NumberValidator extends DataValidator
{
	/**
	 * Constructor method
	 *
	 * @access public
	 * @param object $formObserver The FormObserver to contain this validator
	 */
	function NumberValidator(&$formObserver)
	{
		parent::DataValidator($formObserver);
	}
	
	/**
	 * validate function for number validator class
	 *
	 * Must be a number to be valid
	 *
	 * @access public
	 * @param string $field Name of the form field
	 * @param string $errorMsg Message to be displayed if the field isn't valid
	 * @return boolean Whether the field validated or not
	 */
	function validate($field,$errorMsg)
	{
		parent::validate($field);
		
		if(!isset($this->_method[$field]) || !is_numeric($this->_method[$field]))
		{
			$this->notifyObserver($errorMsg);
			return false;
		}
		
		return true;
	}
}

/**
 * Numberic range validator class to validate a form field as a number within a
 * specific range.
 */
class RangeValidator extends DataValidator
{
	/**
	 * Constructor method
	 *
	 * @access public
	 * @param object $formObserver The FormObserver to contain this validator
	 */
	function RangeValidator(&$formObserver)
	{
		parent::DataValidator($formObserver);
	}
	
	/**
	 * validate function for numeric range validator class
	 *
	 * Must be a number between $min and $max to be valid
	 *
	 * @access public
	 * @param string $field Name of the form field
	 * @param string $errorMsg Message to be displayed if the field isn't valid
	 * @param int $min The minimum number allowed (default=1)
	 * @param int $max The maximum number allowed (default=99)
	 * @return boolean Whether the field validated or not
	 */
	function validate($field,$errorMsg,$min=1,$max=99)
	{
		parent::validate($field);
		
		if(!isset($this->_method[$field]) || $this->_method[$field]<$min || $this->_method[$field]>$max)
		{
			$this->notifyObserver($errorMsg);
			return false;
		}
		
		return true;
	}
}

/**
 * Alphabetic validator class to validate a form field as containing only
 * alphabetic (a-z) characters.
 */
class AlphaValidator extends DataValidator
{
	/**
	 * Constructor method
	 *
	 * @access public
	 * @param object $formObserver The FormObserver to contain this validator
	 */
	function AlphaValidator(&$formObserver)
	{
		parent::DataValidator($formObserver);
	}
	
	/**
	 * validate function for alphabetic validator class
	 *
	 * Must contain only alphabetic characters to be valid
	 *
	 * @access public
	 * @param string $field Name of the form field
	 * @param string $errorMsg Message to be displayed if the field isn't valid
	 * @return boolean Whether the field validated or not
	 */
	function validate($field,$errorMsg)
	{
		parent::validate($field);
		
		if(!isset($this->_method[$field]) || !preg_match('/^[a-zA-Z]+$/',$this->_method[$field]))
		{
			$this->notifyObserver($errorMsg);
			return false;
		}
		
		return true;
	}
}

/**
 * Alphanumeric validator class to validate a form field as containing only
 * alphabetic (a-z) and numeric (0-9) characters.
 */
class AlphanumValidator extends DataValidator
{
	/**
	 * Constructor method
	 *
	 * @access public
	 * @param object $formObserver The FormObserver to contain this validator
	 */
	function AlphanumValidator(&$formObserver)
	{
		parent::DataValidator($formObserver);
	}
	
	/**
	 * validate function for alphanumeric validator class
	 *
	 * Must contain only alphabetic and numeric characters between $min and
	 * $max characters to be valid
	 *
	 * @access public
	 * @param string $field Name of the form field
	 * @param string $errorMsg Message to be displayed if the field isn't valid
	 * @param int $min The minimum size allowed for the string (default=4)
	 * @param int $max The maximum size allowed for the string (default=32)
	 * @return boolean Whether the field validated or not
	 */
	function validate($field,$errorMsg,$min=4,$max=32)
	{
		parent::validate($field);
		
		if(!isset($this->_method[$field])
		||
		!preg_match('/^[a-zA-Z0-9]{'.$min.','.$max.'}$/',$this->_method[$field]))
		{
			$this->notifyObserver($errorMsg);
			return false;
		}
		
		return true;
	}
}

/**
 * Email address validator class to validate email addresses.
 */
class EmailValidator extends DataValidator
{
	/**
	 * Constructor method
	 *
	 * @access public
	 * @param object $formObserver The FormObserver to contain this validator
	 */
	function EmailValidator(&$formObserver)
	{
		parent::DataValidator($formObserver);
	}
	
	/**
	 * validate function for email address validator class
	 *
	 * Must contain a valid email address to be valid
	 *
	 * @access public
	 * @param string $field Name of the form field
	 * @param string $errorMsg Message to be displayed if the field isn't valid
	 * @return boolean Whether the field validated or not
	 */
	function validate($field,$errorMsg)
	{
		parent::validate($field);
		
		if(!isset($this->_method[$field]) || !preg_match('/.+@.+..+/',$this->_method[$field]) || !checkdnsrr(array_pop(explode('@',$this->_method[$field])),'MX'))
		{
			$this->notifyObserver($errorMsg);
			return false;
		}
		
		return true;
	}
}

/**
 * Regular expression validator class to validate strings.
 */
class RegexValidator extends DataValidator
{
	/**
	 * Constructor method
	 *
	 * @access public
	 * @param object $formObserver The FormObserver to contain this validator
	 */
	function RegexValidator(&$formObserver)
	{
		parent::DataValidator($formObserver);
	}
	
	/**
	 * validate function for regular expression validator class
	 *
	 * Must match the supplied regular expression to be valid. Uses PHP ereg()
	 * function
	 *
	 * @access public
	 * @param string $field Name of the form field
	 * @param string $errorMsg Message to be displayed if the field isn't valid
	 * @param string $regex Regular expression to match
	 * @return boolean Whether the field validated or not
	 */
	function validate($field,$errorMsg,$regex)
	{
		parent::validate($field);
		
		if(!isset($this->_method[$field]) || !ereg($regex,$this->_method[$field]))
		{
			$this->notifyObserver($errorMsg);
			return false;
		}
		
		return true;
	}
}

/**
 * Option validator class to validate a match from a supplied array of values.
 */
class OptionValidator extends DataValidator
{
	/**
	 * Constructor method
	 *
	 * @access public
	 * @param object $formObserver The FormObserver to contain this validator
	 */
	function OptionValidator(&$formObserver)
	{
		parent::DataValidator($formObserver);
	}
	
	/**
	 * validate function for option validator class
	 *
	 * Must match one of the supplied values in $options to be valid
	 *
	 * @access public
	 * @param string $field Name of the form field
	 * @param string $errorMsg Message to be displayed if the field isn't valid
	 * @param string $options Array of strings to be tested against
	 * @return boolean Whether the field validated or not
	 */
	function validate($field,$errorMsg,$options=array())
	{
		parent::validate($field);
		
		if(!isset($this->_method[$field]) || !is_array($options) || !in_array($this->_method[$field], $options))
		{
			$this->notifyObserver($errorMsg);
			return false;
		}
		
		return true;
	}
}

/**
 * Date validator class to validate dates.
 */
class DateValidator extends DataValidator
{
	/**
	 * Constructor method
	 *
	 * @access public
	 * @param object $formObserver The FormObserver to contain this validator
	 */
	function DateValidator(&$formObserver)
	{
		parent::DataValidator($formObserver);
	}
	
	/**
	 * validate function for date validator class
	 *
	 * Must be a valid date to be valid
	 *
	 * @todo Improve date matching to make sure an actual valid date is supplied
	 * and that it allows for internationalisation
	 *
	 * @access public
	 * @param string $field Name of the form field
	 * @param string $errorMsg Message to be displayed if the field isn't valid
	 * @return boolean Whether the field validated or not
	 */
	function validate($field,$errorMsg)
	{
		parent::validate($field);
		
		if(!isset($this->_method[$field]) || !eregi('^([0-9]{2}\/){2}[0-9]{4}$',$this->_method[$field]))
		{
			$this->notifyObserver($errorMsg);
			return false;
		}
		
		return true;
	}
}

/**
 * Match validator class to validate strings for exact matches.
 */
class MatchValidator extends DataValidator
{
	/**
	 * Constructor method
	 *
	 * @access public
	 * @param object $formObserver The FormObserver to contain this validator
	 */
	function MatchValidator(&$formObserver)
	{
		parent::DataValidator($formObserver);
	}
	
	/**
	 * validate function for match validator class
	 *
	 * Must match the supplied value exactly to be valid.
	 *
	 * @access public
	 * @param string $field Name of the form field
	 * @param string $errorMsg Message to be displayed if the field isn't valid
	 * @param string $value The value to be matched (default='')
	 * @return boolean Whether the field validated or not
	 */
	function validate($field,$errorMsg,$value='')
	{
		parent::validate($field);
		
		if(!isset($this->_method[$field]) || $this->_method[$field]!=$value)
		{
			$this->notifyObserver($errorMsg);
			return false;
		}
		
		return true;
	}
}

?>
